home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * Sockets routines to handle socket io of an objects. *
- * *
- * Written by: Gershon Elber Ver 0.1, June 1993. *
- *****************************************************************************/
-
- #include <stdio.h>
- #include <sys/types.h>
-
- #ifdef __UNIX__
- #include <signal.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #endif /* __UNIX__ */
-
- #ifdef __WINNT__
- #include <stdlib.h>
- #include <windows.h>
- #include <winsock.h>
- #include <io.h>
- #endif /* __WINNT__ */
-
- #include "irit_sm.h"
- #include "irit_soc.h"
-
- #ifdef OS2GCC
- #define INCL_DOSPROCESS
- #include <os2.h>
-
- static HPIPE
- pipIrit = 0;
- #endif /* OS2GCC */
-
- static int
- GlblBinaryIPC = FALSE,
- GlblMasterSoc = 0,
- GlblCommuSoc = 0;
-
- static void SocketPrintError(char *Str);
- #ifdef __UNIX__
- #if defined(_AIX) || defined(__hpux)
- typedef void (*SignalFuncType)(int);
- #else
- typedef void (*SignalFuncType)(void);
- #endif /* _AIX || __hpux */
- static void SocNoConnectionHandler(void);
- static void SocNoConnectionDummyHandler(void);
- #endif /* __UNIX__ */
-
- /*****************************************************************************
- * IO error print routine. *
- *****************************************************************************/
- static void SocketPrintError(char *Str)
- {
- # if defined(__UNIX__) || defined(OS2GCC)
- perror(Str);
- # endif /* __UNIX__ || OS2GCC */
- # ifdef __WINNT__
- fprintf(stderr, "iritserver: %s error %d\n", Str, WSAGetLastError());
- # endif /* __WINNT__ */
- }
-
- /*****************************************************************************
- * Write a single char. *
- *****************************************************************************/
- void SocServerWriteChar(char c)
- {
- #if defined(__UNIX__) || defined(__WINNT__)
- int i;
-
- if (GlblCommuSoc <= 0) {
- IritPrsrFatalError("Attempt to write to a closed (broken!?) socket");
- return;
- }
-
- while ((i = send(GlblCommuSoc, &c, 1, 0)) != 1) {
- if (i < 0) /* Lost connection probably. */
- SocServerCloseSocket();
- IritSleep(10);
- }
- #endif /* __UNIX__ || __WINNT__ */
- #ifdef OS2GCC
- ULONG BytesWritten;
- ULONG rc;
-
- rc = DosWrite(pipIrit, &c, 1, &BytesWritten);
- #endif /* OS2GCC */
- }
-
- /*****************************************************************************
- * Write a single line of line length characters. *
- *****************************************************************************/
- void SocServerWriteLine(char *Line, int LineLen)
- {
- #if defined(__UNIX__) || defined(__WINNT__)
- int i;
-
- if (GlblCommuSoc <= 0) {
- IritPrsrFatalError("Attempt to write to a closed (broken!?) socket");
- return;
- }
-
- while ((i = send(GlblCommuSoc, Line, LineLen, 0)) < LineLen) {
- if (i < 0) /* Lost connection probably. */
- SocServerCloseSocket();
- IritSleep(10);
- LineLen = LineLen - i;
- Line = &Line[i];
- }
- #endif /* __UNIX__ || __WINNT__ */
- #ifdef OS2GCC
- ULONG BytesWritten;
- ULONG rc;
-
- rc = DosWrite(pipIrit, Line, LineLen, &BytesWritten);
- #endif /* OS2GCC */
- }
-
- /*****************************************************************************
- * Creates a server socket. Returns TRUE if successful. *
- *****************************************************************************/
- int SocServerCreateSocket(void)
- {
- #if defined(__UNIX__) || defined(__WINNT__)
- int s;
- char *portnum;
- struct sockaddr_in sain;
- struct servent *serv;
-
- ZAP_MEM(&sain, sizeof(struct sockaddr_in));
- sain.sin_addr.s_addr = htonl(INADDR_ANY);
- sain.sin_family = AF_INET;
-
- #ifdef __WINNT__
- {
- WSADATA WSAData;
-
- if ((s = WSAStartup(MAKEWORD(1, 1), &WSAData)) != 0) {
- fprintf(stderr, "iritserver: WSAStartup: error %d\n",
- WSAGetLastError());
- exit(1);
- }
- }
- #endif
-
- if ((portnum = getenv("IRIT_SERVER_PORT")) != NULL)
- sain.sin_port = atoi(portnum);
- else if ((serv = getservbyname(IRIT_TCP_SERVICE, "tcp")) == NULL)
- sain.sin_port = htons(IRIT_TCP_PORT);
- else
- sain.sin_port = serv->s_port;
-
- /* Create the socket and bind. */
- if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- IritPrsrFatalError("iritserver: socket");
- return FALSE;
- }
- if (bind(s, (struct sockaddr *) &sain, sizeof(struct sockaddr_in)) < 0) {
- IritPrsrFatalError("iritserver: bind");
- return FALSE;
- }
-
- if (listen(s, 5) < 0) {
- IritPrsrFatalError("iritserver: listen");
- return FALSE;
- }
-
- #ifdef __UNIX__
- signal(SIGPIPE, (SignalFuncType) SocNoConnectionHandler);
- #endif /* __UNIX__ */
-
- GlblMasterSoc = s;
-
- #endif /* __UNIX__ || __WINNT__ */
-
- GlblBinaryIPC = getenv("IRIT_BIN_IPC") != NULL;
-
- return TRUE;
- }
-
- /*****************************************************************************
- * Accept a client socket connection. Blocks until connection is established.*
- *****************************************************************************/
- void SocServerAcceptConnection(void)
- {
- #if defined(__UNIX__) || defined(__WINNT__)
- struct sockaddr_in client_sain;
- int len = sizeof(client_sain);
-
- while ((GlblCommuSoc = accept(GlblMasterSoc,
- (struct sockaddr *) &client_sain,
- &len)) < 0);
- #endif /* __UNIX__ || __WINNT__ */
- #ifdef OS2GCC
- ULONG rc;
- rc = DosCreateNPipe(IRIT_PIPE, /* Drawing command pipe. */
- &pipIrit,
- NP_ACCESS_DUPLEX | NP_NOWRITEBEHIND,
- NP_WAIT | NP_TYPE_BYTE | NP_READMODE_BYTE | 1,
- IRIT_PIPE_BUFFER_SIZE,
- IRIT_PIPE_BUFFER_SIZE,
- 0);
-
- if (rc != 0) {
- fprintf(stderr,
- "DosCreateNPipe: error in creating %s\n", IRIT_PIPE);
- exit(1);
- }
-
- if ((rc = DosConnectNPipe(pipIrit)) != 0) {
- fprintf(stderr,
- "DosConnectNPipe: error in connection %s\n",
- IRIT_PIPE);
- exit(1);
- }
-
- GlblCommuSoc = (int) pipIrit;
- #endif /* OS2GCC */
- }
-
- /*****************************************************************************
- * Close a server socket. *
- *****************************************************************************/
- void SocServerCloseSocket(void)
- {
- if (GlblCommuSoc > 0) {
- #ifdef __UNIX__
- char Line[LINE_LEN];
-
- /* Force the system to realize that the connection is down. This is */
- /* a kluge to solve the time out problem that happens under unix. */
- IritSleep(1000);
- signal(SIGPIPE, (SignalFuncType) SocNoConnectionDummyHandler);
- send(GlblCommuSoc, Line, LINE_LEN, 0);
-
- if (close(GlblCommuSoc) != 0)
- SocketPrintError("iritserver: close");
- #endif /* __UNIX__ */
- #ifdef __WINNT__
- closesocket(GlblCommuSoc);
- #endif /* __WINNT__ */
-
- GlblCommuSoc = 0;
- }
- }
-
- /*****************************************************************************
- * Returns TRUE if connection is active. *
- *****************************************************************************/
- int SocServerActive(void)
- {
- return GlblCommuSoc > 0;
- }
-
- #ifdef __UNIX__
- /*****************************************************************************
- * Clean the server socket in case of a broken pipe. *
- *****************************************************************************/
- static void SocNoConnectionHandler(void)
- {
- SocServerCloseSocket();
- signal(SIGPIPE, (SignalFuncType) SocNoConnectionHandler);
- IritPrsrParserAbort(IP_ERR_SOCKET_BROKEN, "");
- }
- /*****************************************************************************
- * Dummy handler *
- *****************************************************************************/
- static void SocNoConnectionDummyHandler(void)
- {
- }
- #endif /* __UNIX__ */
-
- /*****************************************************************************
- * Attempt to write an object to a socket. *
- *****************************************************************************/
- void SocServerWriteOneObject(IPObjectStruct *PObj)
- {
- char *ErrorMsg;
-
- if (GlblCommuSoc <= 0) {
- char *DisplayStr;
-
- /* Needs to start up the client display - it is not up yet */
- if ((DisplayStr = getenv("IRIT_DISPLAY")) != NULL) {
- #ifdef OS2GCC
- char LoadError[LINE_LEN], Env[LINE_LEN];
- RESULTCODES Results;
- ULONG rc;
- int i;
-
- strcpy(Env, "IRIT_DISPLAY_S=1");
- i = strlen(Env) + 1;
- if (GlblBinaryIPC) {
- strcpy(&Env[i], "IRIT_BIN_IPC=1");
- i += strlen(&Env[i]) + 1;
- }
- Env[i] = '\0';
-
- LoadError[0] = 0;
- rc = DosExecPgm(LoadError,
- sizeof(LoadError),
- EXEC_BACKGROUND,
- "",
- Env,
- &Results,
- DisplayStr);
- if (rc != 0) {
- fprintf(stderr,
- "DosExecPgm: (Error %d) \"%s\"\n", rc, LoadError);
- exit(1);
- }
- #else
- #ifdef __UNIX__
- char DisplayCommand[LINE_LEN];
-
- sprintf(DisplayCommand, "%s &", DisplayStr);
- system(DisplayCommand);
- #else
- #ifdef __WINNT__
- char DisplayCommand[LINE_LEN];
-
- sprintf(DisplayCommand, "start %s", DisplayStr);
- system(DisplayCommand);
- #else
- #endif /* __WINNT__ */
- #endif /* __UNIX__ */
- #endif /* OS2GCC */
- }
- else
- fprintf(stderr,
- "Irit: Startup your display device - I am waiting...\n");
- SocServerAcceptConnection();
- fprintf(stderr, "Irit: Connection with client established.\n");
-
- #ifdef __UNIX__
- signal(SIGPIPE, (SignalFuncType) SocNoConnectionHandler);
- #endif /* __UNIX__ */
- }
-
- if (IP_IS_UNDEF_OBJ(PObj)) {
- fprintf(stderr, "Socket: Attempt to write an undefined object.\n");
- return;
- }
-
- IritPrsrWriteSocket(TRUE);
- if (GlblBinaryIPC) {
- IritPrsrPutBinObject(NULL, PObj);
- }
- else {
- IritPrsrPutObject(NULL, PObj);
- }
- IritPrsrWriteSocket(FALSE);
-
- if (IritPrsrParseError(&ErrorMsg)) {
- fprintf(stderr, "Socket: %s\n", ErrorMsg);
- }
- }
-
- #ifdef DEBUG_SERVER
-
- /*****************************************************************************
- * Simple test for the server - reads file and dumps one object every key. *
- *****************************************************************************/
- void main(int argc, char ** argv)
- {
- FILE
- *f = argc == 2 ? fopen(argv[1], "r") : stdin;
- IPObjectStruct *PObj,
- *PObjClear = IPAllocObject("_COMMAND_", IP_OBJ_STRING, NULL),
- *PObjs = IritPrsrGetObjects(f);
-
- if (argc == 2)
- fclose(f);
- strcpy(PObjClear -> U.Str, "CLEAR");
-
- SocServerCreateSocket();
-
- while (TRUE) {
- for (PObj = PObjs; PObj != NULL; PObj = PObj -> Pnext) {
- fprintf(stderr, "Press return to send data.\n");
- getchar();
- SocServerWriteOneObject(PObj);
- }
-
- fprintf(stderr, "Done. Press return to send clear.\n");
- getchar();
- SocServerWriteOneObject(PObjClear);
- }
-
- SocServerCloseSocket();
- }
-
- #endif /* DEBUG_SERVER */
-